import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import chess
import chess.engine
import chess.svg
import cairosvg
from PIL import Image, ImageTk, ImageDraw, ImageFilter
import io
import os
import threading
import queue
import math
import recognise
import numpy as np

class ChessGUI:

    def __init__(self, master):
        self.master = master
        self.master.title("国际象棋")
        self.master.geometry("1400x900")
        self.master.configure(bg='#1a1a1a')
        
        try:
            self.master.iconbitmap('chess.ico')
        except:
            pass
        
        self.setup_styles()
        self.colors = {
            'bg_dark': '#1a1a1a',
            'bg_medium': '#2d2d2d',
            'bg_light': '#3a3a3a',
            'accent': '#4a9eff',
            'accent_hover': '#66b0ff',
            'text_primary': '#ffffff',
            'text_secondary': '#b0b0b0',
            'success': '#4caf50',
            'warning': '#ff9800',
            'danger': '#f44336',
            'board_light': '#f0d9b5',
            'board_dark': '#b58863',
            'board_light_selected': '#f7ec5f',
            'board_dark_selected': '#dac748',
            'board_light_hover': '#f5e4c3',
            'board_dark_hover': '#c49a75',
            'move_hint': 'rgba(74, 158, 255, 0.5)',
            'last_move_from': 'rgba(255, 255, 100, 0.4)',
            'last_move_to': 'rgba(255, 255, 100, 0.6)'
        }
        
        self.board = chess.Board()
        self.selected_square = None
        self.hover_square = None
        self.legal_moves = []
        self.move_history = []
        self.last_move = None
        self.engine = None
        self.engine_path = None
        self.analysis_queue = queue.Queue()
        self.is_flipped = False
        self.is_analyzing = False
        self.analysis_thread = None
        self.show_coordinates = True
        self.show_legal_moves = True
        self.sound_enabled = True
        
        self.animation_pieces = {}
        self.animation_running = False
        
        self.piece_images = {}
        self.piece_shadows = {}
        self.load_piece_images()
        
        self.create_widgets()
        
        self.draw_board()
        
        self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
        
    def setup_styles(self):
        style = ttk.Style()
        style.theme_use('clam')
        
        style.configure('Primary.TButton',
                       background='#4a9eff',
                       foreground='white',
                       borderwidth=0,
                       focuscolor='none',
                       padding=(15, 8),
                       font=('Segoe UI', 10))
        style.map('Primary.TButton',
                 background=[('active', '#66b0ff')])
        
        style.configure('Secondary.TButton',
                       background='#3a3a3a',
                       foreground='white',
                       borderwidth=0,
                       focuscolor='none',
                       padding=(12, 6),
                       font=('Segoe UI', 9))
        style.map('Secondary.TButton',
                 background=[('active', '#4a4a4a')])
        
        style.configure('Danger.TButton',
                       background='#f44336',
                       foreground='white',
                       borderwidth=0,
                       focuscolor='none',
                       padding=(12, 6),
                       font=('Segoe UI', 9))
        style.map('Danger.TButton',
                 background=[('active', '#ff6659')])
        
        style.configure('Title.TLabel',
                       background='#1a1a1a',
                       foreground='white',
                       font=('Segoe UI', 14, 'bold'))
        
        style.configure('Main.TLabel',
                       background='#1a1a1a',
                       foreground='white',
                       font=('Segoe UI', 10))
        
        style.configure('Status.TLabel',
                       background='#2d2d2d',
                       foreground='white',
                       font=('Segoe UI', 11),
                       padding=(10, 5))
        
        style.configure('Main.TFrame',
                       background='#1a1a1a')
        
        style.configure('Card.TFrame',
                       background='#2d2d2d',
                       relief='flat',
                       borderwidth=1)
        
        style.configure('Card.TLabelframe',
                       background='#2d2d2d',
                       foreground='white',
                       borderwidth=0,
                       font=('Segoe UI', 11, 'bold'))
        style.configure('Card.TLabelframe.Label',
                       background='#2d2d2d',
                       foreground='#4a9eff')
        
        style.configure('Main.TCheckbutton',
                       background='#2d2d2d',
                       foreground='white',
                       focuscolor='none',
                       font=('Segoe UI', 9))

    def load_piece_images(self):
        pieces_svg = {
            'wK': 'chess_icons/wK.svg', 'wQ': 'chess_icons/wQ.svg',
            'wR': 'chess_icons/wR.svg', 'wB': 'chess_icons/wB.svg',
            'wN': 'chess_icons/wN.svg', 'wP': 'chess_icons/wP.svg',
            'bK': 'chess_icons/bK.svg', 'bQ': 'chess_icons/bQ.svg',
            'bR': 'chess_icons/bR.svg', 'bB': 'chess_icons/bB.svg',
            'bN': 'chess_icons/bN.svg', 'bP': 'chess_icons/bP.svg'
        }
        
        svg_loaded = False
        
        for piece_name, svg_path in pieces_svg.items():
            if os.path.exists(svg_path):
                try:
                    png_data = cairosvg.svg2png(url=svg_path, output_width=60, output_height=60)
                    image = Image.open(io.BytesIO(png_data))
                    self.piece_images[piece_name] = ImageTk.PhotoImage(image)
                    svg_loaded = True
                except Exception as e:
                    print(f"加载SVG失败 {piece_name}: {e}")
        
            
                
            
    def create_widgets(self):
        header_frame = ttk.Frame(self.master, style='Main.TFrame', height=60)
        header_frame.pack(fill=tk.X, padx=20, pady=(10, 0))
        header_frame.pack_propagate(False)
        
        title_label = ttk.Label(header_frame, text="国际象棋大师", style='Title.TLabel')
        title_label.pack(side=tk.LEFT, pady=15)
        
        main_container = ttk.Frame(self.master, style='Main.TFrame')
        main_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
        
        board_container = ttk.Frame(main_container, style='Card.TFrame')
        board_container.pack(side=tk.LEFT, padx=(0, 20))
        
        board_frame = ttk.Frame(board_container, style='Card.TFrame')
        board_frame.pack(padx=20, pady=20)
        
        self.canvas = tk.Canvas(board_frame, width=640, height=640, 
                               bg='#2d2d2d', highlightthickness=0)
        self.canvas.pack()
        
        board_controls = ttk.Frame(board_container, style='Card.TFrame')
        board_controls.pack(fill=tk.X, padx=20, pady=(0, 20))
        
        ttk.Button(board_controls, text="翻转棋盘", 
                  command=self.flip_board, style='Secondary.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(board_controls, text="撤销", 
                  command=self.undo_move, style='Secondary.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(board_controls, text="新游戏", 
                  command=self.new_game, style='Danger.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(board_controls, text="保存棋盘", 
                  command=self.save_board_image, style='Primary.TButton').pack(side=tk.LEFT, padx=5)
        
        control_container = ttk.Frame(main_container, style='Main.TFrame')
        control_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        canvas_scroll = tk.Canvas(control_container, bg='#1a1a1a', highlightthickness=0)
        scrollbar = ttk.Scrollbar(control_container, orient="vertical", command=canvas_scroll.yview)
        scrollable_frame = ttk.Frame(canvas_scroll, style='Main.TFrame')
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas_scroll.configure(scrollregion=canvas_scroll.bbox("all"))
        )
        
        canvas_scroll.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas_scroll.configure(yscrollcommand=scrollbar.set)
        
        canvas_scroll.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        fen_frame = ttk.LabelFrame(scrollable_frame, text="FEN码", style='Card.TLabelframe')
        fen_frame.pack(fill=tk.X, pady=(0, 15))
        
        fen_inner = ttk.Frame(fen_frame, style='Card.TFrame')
        fen_inner.pack(fill=tk.X, padx=15, pady=10)
        
        self.fen_entry = tk.Entry(fen_inner, font=('Consolas', 11), 
                                 bg='#3a3a3a', fg='white', 
                                 insertbackground='#4a9eff',
                                 relief=tk.FLAT, bd=10)
        self.fen_entry.pack(fill=tk.X, pady=(0, 10))
        self.fen_entry.insert(0, self.board.fen())
        
        fen_buttons = ttk.Frame(fen_inner, style='Card.TFrame')
        fen_buttons.pack(fill=tk.X)
        
        ttk.Button(fen_buttons, text="加载FEN", 
                  command=self.load_fen, style='Primary.TButton').pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(fen_buttons, text="复制FEN", 
                  command=self.copy_fen, style='Secondary.TButton').pack(side=tk.LEFT)
        
        engine_frame = ttk.LabelFrame(scrollable_frame, text="引擎分析", style='Card.TLabelframe')
        engine_frame.pack(fill=tk.X, pady=(0, 15))
        
        engine_inner = ttk.Frame(engine_frame, style='Card.TFrame')
        engine_inner.pack(fill=tk.X, padx=15, pady=10)
        
        engine_buttons = ttk.Frame(engine_inner, style='Card.TFrame')
        engine_buttons.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Button(engine_buttons, text="加载引擎", 
                  command=self.load_engine, style='Primary.TButton').pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(engine_buttons, text="分析局面", 
                  command=self.analyze_position, style='Secondary.TButton').pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(engine_buttons, text="最佳着法", 
                  command=self.get_best_move, style='Secondary.TButton').pack(side=tk.LEFT)
        
        self.auto_analyze_var = tk.BooleanVar()
        auto_check = ttk.Checkbutton(engine_buttons, text="自动分析", 
                                    variable=self.auto_analyze_var,
                                    command=self.toggle_auto_analysis, 
                                    style='Main.TCheckbutton')
        auto_check.pack(side=tk.LEFT, padx=(10, 0))
        
        analysis_frame = ttk.Frame(engine_inner, style='Card.TFrame')
        analysis_frame.pack(fill=tk.X)
        
        self.analysis_text = tk.Text(analysis_frame, height=8, font=('Consolas', 10), 
                                    bg='#1a1a1a', fg='#4a9eff', 
                                    insertbackground='#4a9eff',
                                    relief=tk.FLAT, bd=10,
                                    wrap=tk.WORD)
        self.analysis_text.pack(fill=tk.X)
        
        history_frame = ttk.LabelFrame(scrollable_frame, text="走法历史", style='Card.TLabelframe')
        history_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 15))
        
        history_inner = ttk.Frame(history_frame, style='Card.TFrame')
        history_inner.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)
        
        history_text_frame = ttk.Frame(history_inner, style='Card.TFrame')
        history_text_frame.pack(fill=tk.BOTH, expand=True)
        
        history_scroll = ttk.Scrollbar(history_text_frame)
        history_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.history_text = tk.Text(history_text_frame, height=12, 
                                   font=('Consolas', 10),
                                   bg='#1a1a1a', fg='white', 
                                   insertbackground='#4a9eff',
                                   relief=tk.FLAT, bd=10,
                                   yscrollcommand=history_scroll.set)
        self.history_text.pack(fill=tk.BOTH, expand=True)
        history_scroll.config(command=self.history_text.yview)
        
        settings_frame = ttk.LabelFrame(scrollable_frame, text="设置", style='Card.TLabelframe')
        settings_frame.pack(fill=tk.X, pady=(0, 15))
        
        settings_inner = ttk.Frame(settings_frame, style='Card.TFrame')
        settings_inner.pack(fill=tk.X, padx=15, pady=10)
        
        self.show_coords_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(settings_inner, text="显示坐标", 
                       variable=self.show_coords_var,
                       command=self.toggle_coordinates,
                       style='Main.TCheckbutton').pack(anchor=tk.W, pady=2)
        
        self.show_moves_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(settings_inner, text="显示可能的移动", 
                       variable=self.show_moves_var,
                       command=self.toggle_legal_moves,
                       style='Main.TCheckbutton').pack(anchor=tk.W, pady=2)
        
        status_frame = ttk.Frame(self.master, style='Card.TFrame')
        status_frame.pack(fill=tk.X, side=tk.BOTTOM, padx=20, pady=(0, 20))
        
        self.status_label = ttk.Label(status_frame, text="白方走棋", style='Status.TLabel')
        self.status_label.pack(pady=5)
        
        self.canvas.bind("<Button-1>", self.on_board_click)
        self.canvas.bind("<Motion>", self.on_mouse_motion)
        self.canvas.bind("<Leave>", self.on_mouse_leave)
        
    def draw_board(self):
        self.canvas.delete("all")
        
        for row in range(8):
            for col in range(8):
                x1 = col * 80
                y1 = row * 80
                x2 = x1 + 80
                y2 = y1 + 80
                
                square = chess.square(col, 7 - row) if not self.is_flipped else chess.square(7 - col, row)
                
                if (row + col) % 2 == 0:
                    color = self.colors['board_light']
                else:
                    color = self.colors['board_dark']
                
                if self.last_move:
                    if square == self.last_move.from_square:
                        color = '#c8c855' if (row + col) % 2 == 0 else '#b8b845'
                    elif square == self.last_move.to_square:
                        color = '#d8d865' if (row + col) % 2 == 0 else '#c8c855'
                
                if square == self.selected_square:
                    color = self.colors['board_light_selected'] if (row + col) % 2 == 0 else self.colors['board_dark_selected']
                
                if square == self.hover_square and square != self.selected_square:
                    color = self.colors['board_light_hover'] if (row + col) % 2 == 0 else self.colors['board_dark_hover']
                
                self.canvas.create_rectangle(x1, y1, x2, y2, fill=color, outline="", tags=f"square_{square}")
                
                if self.show_moves_var.get() and square in self.legal_moves:
                    if self.board.piece_at(square):
                        points = [
                            x1 + 5, y1 + 5,
                            x1 + 25, y1 + 5,
                            x1 + 5, y1 + 25
                        ]
                        self.canvas.create_polygon(points, fill='#ff4444', outline='')
                        points = [
                            x2 - 5, y1 + 5,
                            x2 - 25, y1 + 5,
                            x2 - 5, y1 + 25
                        ]
                        self.canvas.create_polygon(points, fill='#ff4444', outline='')
                        points = [
                            x1 + 5, y2 - 5,
                            x1 + 25, y2 - 5,
                            x1 + 5, y2 - 25
                        ]
                        self.canvas.create_polygon(points, fill='#ff4444', outline='')
                        points = [
                            x2 - 5, y2 - 5,
                            x2 - 25, y2 - 5,
                            x2 - 5, y2 - 25
                        ]
                        self.canvas.create_polygon(points, fill='#ff4444', outline='')
                    else:
                        self.canvas.create_oval(x1 + 32, y1 + 32, x1 + 48, y1 + 48,
                                              fill='#4a9eff', outline='')
                
                if self.show_coords_var.get():
                    if col == 0:
                        rank = str(8 - row) if not self.is_flipped else str(row + 1)
                        self.canvas.create_text(x1 + 8, y1 + 8, text=rank,
                                              font=('Arial', 11, 'bold'), 
                                              fill='#888888' if (row + col) % 2 == 0 else '#666666',
                                              anchor='nw')
                    if row == 7:
                        file = chr(ord('a') + col) if not self.is_flipped else chr(ord('h') - col)
                        self.canvas.create_text(x2 - 8, y2 - 8, text=file,
                                              font=('Arial', 11, 'bold'), 
                                              fill='#888888' if (row + col) % 2 == 0 else '#666666',
                                              anchor='se')
        
        for square in chess.SQUARES:
            piece = self.board.piece_at(square)
            if piece:
                file = chess.square_file(square)
                rank = chess.square_rank(square)
                
                if self.is_flipped:
                    x = (7 - file) * 80 + 40
                    y = rank * 80 + 40
                else:
                    x = file * 80 + 40
                    y = (7 - rank) * 80 + 40
                
                color = 'w' if piece.color else 'b'
                piece_type = piece.symbol().upper()
                piece_key = f"{color}{piece_type}"
                
                if piece_key in self.piece_images:
                    if piece_key in self.piece_shadows:
                        self.canvas.create_image(x + 3, y + 3, image=self.piece_shadows[piece_key], 
                                               tags=f"piece_{square}")
                    self.canvas.create_image(x, y, image=self.piece_images[piece_key], 
                                           tags=f"piece_{square}")
                    
    def save_board_image(self):
        filename = filedialog.asksaveasfilename(
            title="保存棋盘图片",
            defaultextension=".png",
            filetypes=[("PNG图片", "*.png"), ("JPEG图片", "*.jpg"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                board_image = Image.new('RGB', (640, 640), color='white')
                draw = ImageDraw.Draw(board_image)
                
                for row in range(8):
                    for col in range(8):
                        x1 = col * 80
                        y1 = row * 80
                        x2 = x1 + 80
                        y2 = y1 + 80
                        
                        square = chess.square(col, 7 - row) if not self.is_flipped else chess.square(7 - col, row)
                        
                        if (row + col) % 2 == 0:
                            color = self.colors['board_light']
                        else:
                            color = self.colors['board_dark']
                        
                        if self.last_move:
                            if square == self.last_move.from_square:
                                color = '#c8c855' if (row + col) % 2 == 0 else '#b8b845'
                            elif square == self.last_move.to_square:
                                color = '#d8d865' if (row + col) % 2 == 0 else '#c8c855'
                        
                        draw.rectangle([x1, y1, x2, y2], fill=color)
                        
                        if self.show_coords_var.get():
                            if col == 0:
                                rank = str(8 - row) if not self.is_flipped else str(row + 1)
                                draw.text((x1 + 8, y1 + 8), rank, fill='#666666', font=None)
                            if row == 7:
                                file = chr(ord('a') + col) if not self.is_flipped else chr(ord('h') - col)
                                draw.text((x2 - 15, y2 - 20), file, fill='#666666', font=None)
                
                svg_string = chess.svg.board(board=self.board, flipped=self.is_flipped, coordinates=False)
                png_data = cairosvg.svg2png(bytestring=svg_string.encode('utf-8'), output_width=640, output_height=640)
                pieces_image = Image.open(io.BytesIO(png_data))
                
                pieces_image = pieces_image.convert("RGBA")
                board_image.paste(pieces_image, (0, 0), pieces_image)
                
                board_image.save(filename)
                self.show_notification(f"棋盘已保存为: {os.path.basename(filename)}", "success")
                
            except Exception as e:
                messagebox.showerror("错误", f"保存图片失败: {str(e)}")
                    
    def on_board_click(self, event):
        col = event.x // 80
        row = event.y // 80
        
        if 0 <= col < 8 and 0 <= row < 8:
            if self.is_flipped:
                square = chess.square(7 - col, row)
            else:
                square = chess.square(col, 7 - row)
            
            if self.selected_square is None:
                piece = self.board.piece_at(square)
                if piece and piece.color == self.board.turn:
                    self.selected_square = square
                    self.legal_moves = [move.to_square for move in self.board.legal_moves
                                      if move.from_square == square]
                    self.draw_board()
            else:
                move = None
                for legal_move in self.board.legal_moves:
                    if legal_move.from_square == self.selected_square and legal_move.to_square == square:
                        if self.board.piece_at(self.selected_square).piece_type == chess.PAWN:
                            if (self.board.turn == chess.WHITE and chess.square_rank(square) == 7) or \
                               (self.board.turn == chess.BLACK and chess.square_rank(square) == 0):
                                move = self.show_promotion_dialog(self.selected_square, square)
                                if not move:
                                    self.selected_square = None
                                    self.legal_moves = []
                                    self.draw_board()
                                    return
                                break
                        move = legal_move
                        break
                
                if move:
                    self.make_move(move)
                
                self.selected_square = None
                self.legal_moves = []
                self.draw_board()
                
    def on_mouse_motion(self, event):
        col = event.x // 80
        row = event.y // 80
        
        if 0 <= col < 8 and 0 <= row < 8:
            if self.is_flipped:
                square = chess.square(7 - col, row)
            else:
                square = chess.square(col, 7 - row)
            
            if square != self.hover_square:
                self.hover_square = square
                self.draw_board()
        else:
            if self.hover_square is not None:
                self.hover_square = None
                self.draw_board()
                
    def on_mouse_leave(self, event):
        if self.hover_square is not None:
            self.hover_square = None
            self.draw_board()
            
    def show_promotion_dialog(self, from_square, to_square):
        dialog = tk.Toplevel(self.master)
        dialog.title("选择升变棋子")
        dialog.geometry("320x120")
        dialog.configure(bg='#2d2d2d')
        dialog.transient(self.master)
        dialog.grab_set()
        
        dialog.update_idletasks()
        x = (dialog.winfo_screenwidth() - dialog.winfo_width()) // 2
        y = (dialog.winfo_screenheight() - dialog.winfo_height()) // 2
        dialog.geometry(f"+{x}+{y}")
        
        label = tk.Label(dialog, text="选择要升变的棋子:", 
                        font=('Segoe UI', 12), bg='#2d2d2d', fg='white')
        label.pack(pady=10)
        
        button_frame = tk.Frame(dialog, bg='#2d2d2d')
        button_frame.pack(pady=10)
        
        promotion_choice = [None]
        
        pieces = [
            (chess.QUEEN, "♕" if self.board.turn else "♛", "皇后"),
            (chess.ROOK, "♖" if self.board.turn else "♜", "车"),
            (chess.BISHOP, "♗" if self.board.turn else "♝", "象"),
            (chess.KNIGHT, "♘" if self.board.turn else "♞", "马")
        ]
        
        for piece_type, symbol, name in pieces:
            btn = tk.Button(button_frame, text=f"{symbol}\n{name}", 
                          font=('Arial', 16), width=4, height=2,
                          bg='#4a9eff', fg='white', bd=0,
                          activebackground='#66b0ff',
                          command=lambda pt=piece_type: [
                              setattr(promotion_choice, 0, chess.Move(from_square, to_square, promotion=pt)),
                              dialog.destroy()
                          ])
            btn.pack(side=tk.LEFT, padx=5)
        
        dialog.wait_window()
        return promotion_choice[0]
        
    def make_move(self, move):
        san = self.board.san(move)
        self.last_move = move
        
        self.board.push(move)
        self.move_history.append(san)
        
        self.update_history()
        self.update_fen_display()
        self.update_status()
        self.draw_board()
        
        if self.auto_analyze_var.get() and self.engine:
            self.start_auto_analysis()
            
    def update_history(self):
        self.history_text.delete(1.0, tk.END)
        
        for i in range(0, len(self.move_history), 2):
            move_num = i // 2 + 1
            white_move = self.move_history[i]
            black_move = self.move_history[i + 1] if i + 1 < len(self.move_history) else ""
            
            self.history_text.insert(tk.END, f"{move_num}. ", 'move_number')
            self.history_text.insert(tk.END, f"{white_move} ", 'white_move')
            if black_move:
                self.history_text.insert(tk.END, f"{black_move} ", 'black_move')
            self.history_text.insert(tk.END, "\n")
            
        self.history_text.tag_config('move_number', foreground='#4a9eff', font=('Consolas', 10, 'bold'))
        self.history_text.tag_config('white_move', foreground='#ffffff', font=('Consolas', 10))
        self.history_text.tag_config('black_move', foreground='#b0b0b0', font=('Consolas', 10))
        
        self.history_text.see(tk.END)
        
    def update_fen_display(self):
        self.fen_entry.delete(0, tk.END)
        self.fen_entry.insert(0, self.board.fen())
        
    def update_status(self):
        if self.board.is_checkmate():
            winner = "黑方" if self.board.turn else "白方"
            self.status_label.config(text=f"将死 - {winner}获胜!")
            self.show_game_over_dialog(f"{winner}获胜!", "将死")
        elif self.board.is_stalemate():
            self.status_label.config(text="和棋 - 逼和")
            self.show_game_over_dialog("和棋", "逼和")
        elif self.board.is_insufficient_material():
            self.status_label.config(text="和棋 - 子力不足")
            self.show_game_over_dialog("和棋", "子力不足")
        elif self.board.is_check():
            turn = "白方" if self.board.turn else "黑方"
            self.status_label.config(text=f"⚠️ {turn}被将军!")
        else:
            turn = "白方" if self.board.turn else "黑方"
            self.status_label.config(text=f"{turn}走棋")
            
    def show_game_over_dialog(self, title, message):
        dialog = tk.Toplevel(self.master)
        dialog.title("游戏结束")
        dialog.geometry("300x150")
        dialog.configure(bg='#2d2d2d')
        dialog.transient(self.master)
        
        dialog.update_idletasks()
        x = (dialog.winfo_screenwidth() - dialog.winfo_width()) // 2
        y = (dialog.winfo_screenheight() - dialog.winfo_height()) // 2
        dialog.geometry(f"+{x}+{y}")
        
        title_label = tk.Label(dialog, text=title, font=('Segoe UI', 16, 'bold'),
                             bg='#2d2d2d', fg='#4a9eff')
        title_label.pack(pady=(20, 10))
        
        msg_label = tk.Label(dialog, text=message, font=('Segoe UI', 12),
                           bg='#2d2d2d', fg='white')
        msg_label.pack(pady=(0, 20))
        
        button_frame = tk.Frame(dialog, bg='#2d2d2d')
        button_frame.pack()
        
        tk.Button(button_frame, text="新游戏", font=('Segoe UI', 10),
                 bg='#4a9eff', fg='white', bd=0, padx=20, pady=5,
                 activebackground='#66b0ff',
                 command=lambda: [dialog.destroy(), self.new_game()]).pack(side=tk.LEFT, padx=5)
        
        tk.Button(button_frame, text="关闭", font=('Segoe UI', 10),
                 bg='#3a3a3a', fg='white', bd=0, padx=20, pady=5,
                 activebackground='#4a4a4a',
                 command=dialog.destroy).pack(side=tk.LEFT, padx=5)
        
    def new_game(self):
        if len(self.move_history) > 0:
            if not messagebox.askyesno("新游戏", "确定要开始新游戏吗？当前游戏进度将丢失。"):
                return
        
        self.board = chess.Board()
        self.selected_square = None
        self.hover_square = None
        self.legal_moves = []
        self.move_history = []
        self.last_move = None
        
        self.update_fen_display()
        self.history_text.delete(1.0, tk.END)
        self.analysis_text.delete(1.0, tk.END)
        
        self.update_status()
        self.draw_board()
        
    def flip_board(self):
        self.is_flipped = not self.is_flipped
        self.draw_board()
        
    def undo_move(self):
        if self.board.move_stack:
            self.board.pop()
            if self.move_history:
                self.move_history.pop()
            
            if self.board.move_stack:
                self.last_move = self.board.move_stack[-1]
            else:
                self.last_move = None
            
            self.update_fen_display()
            self.update_history()
            self.update_status()
            self.draw_board()
            
    def load_fen(self,fen=None):
        # load_fen 函数加载当前输入框内的FEN字符串到棋盘上
        if fen is None:
            fen = self.fen_entry.get().strip()
        # fen就是加载的FEN字符串
        self.fen_entry.delete(0, tk.END)
        self.fen_entry.insert(0, fen)
        try:
            self.board = chess.Board(fen.strip())
            self.selected_square = None
            self.hover_square = None
            self.legal_moves = []
            self.move_history = []
            self.last_move = None
            
            self.history_text.delete(1.0, tk.END)
            self.analysis_text.delete(1.0, tk.END)
            
            self.update_status()
            self.draw_board()
            
            self.show_notification("FEN码加载成功", "success")
        except Exception as e:
            messagebox.showerror("错误", f"无效的FEN码: {str(e)}")
            print(f"加载FEN失败: {str(e)}")
            
    def copy_fen(self):
        self.master.clipboard_clear()
        self.master.clipboard_append(self.board.fen())
        self.show_notification("FEN码已复制到剪贴板", "success")
        
    def show_notification(self, message, type="info"):
        notification = tk.Toplevel(self.master)
        notification.overrideredirect(True)
        notification.configure(bg='#2d2d2d')
        
        colors = {
            'success': '#4caf50',
            'warning': '#ff9800',
            'error': '#f44336',
            'info': '#4a9eff'
        }
        color = colors.get(type, '#4a9eff')
        
        label = tk.Label(notification, text=message, 
                        font=('Segoe UI', 11),
                        bg=color, fg='white', padx=20, pady=10)
        label.pack()
        
        notification.update_idletasks()
        x = self.master.winfo_x() + (self.master.winfo_width() - notification.winfo_width()) // 2
        y = self.master.winfo_y() + 100
        notification.geometry(f"+{x}+{y}")
        
        notification.after(2000, notification.destroy)
        
    def load_engine(self):
        filename = filedialog.askopenfilename(
            title="选择国际象棋引擎",
            filetypes=[("可执行文件", "*.exe"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                if self.engine:
                    self.engine.quit()
                
                self.engine_path = filename
                self.engine = chess.engine.SimpleEngine.popen_uci(filename)
                
                engine_name = self.engine.id.get("name", "Unknown Engine")
                self.analysis_text.delete(1.0, tk.END)
                self.analysis_text.insert(tk.END, f"引擎已加载: {engine_name}\n", 'success')
                self.analysis_text.insert(tk.END, "可以开始分析了！\n", 'info')
                
                self.analysis_text.tag_config('success', foreground='#4caf50')
                self.analysis_text.tag_config('info', foreground='#4a9eff')
                self.analysis_text.tag_config('warning', foreground='#ff9800')
                self.analysis_text.tag_config('error', foreground='#f44336')
                
                self.show_notification("引擎加载成功", "success")
            except Exception as e:
                messagebox.showerror("错误", f"加载引擎失败: {str(e)}")
                
    def analyze_position(self):
        if not self.engine:
            messagebox.showwarning("警告", "请先加载引擎")
            return
            
        def analyze():
            try:
                self.analysis_text.delete(1.0, tk.END)
                self.analysis_text.insert(tk.END, "正在分析...\n", 'info')
                
                info = self.engine.analyse(self.board, chess.engine.Limit(time=3.0))
                
                self.analysis_text.delete(1.0, tk.END)
                
                score = info.get("score", None)
                if score:
                    pov_score = score.relative
                    if pov_score.is_mate():
                        mate_in = pov_score.mate()
                        if mate_in > 0:
                            eval_text = f"白方 {mate_in} 步将死"
                            tag = 'success' if self.board.turn else 'error'
                        else:
                            eval_text = f"黑方 {-mate_in} 步将死"
                            tag = 'error' if self.board.turn else 'success'
                    else:
                        cp = pov_score.score()
                        if cp is not None:
                            cp = cp / 100.0
                            eval_text = f"评估: {cp:+.2f}"
                            if abs(cp) < 0.5:
                                tag = 'info'
                            elif cp > 0:
                                tag = 'success' if self.board.turn else 'warning'
                            else:
                                tag = 'warning' if self.board.turn else 'success'
                        else:
                            eval_text = "评估: 0.00"
                            tag = 'info'
                else:
                    eval_text = "无法评估"
                    tag = 'warning'
                    
                self.analysis_text.insert(tk.END, eval_text + "\n\n", tag)
                
                pv = info.get("pv", [])
                if pv:
                    self.analysis_text.insert(tk.END, "主要变化: ", 'info')
                    temp_board = self.board.copy()
                    for i, move in enumerate(pv[:10]):
                        try:
                            san = temp_board.san(move)
                            if i % 2 == 0:
                                move_num = temp_board.fullmove_number
                                self.analysis_text.insert(tk.END, f"\n{move_num}. ", 'info')
                            self.analysis_text.insert(tk.END, f"{san} ")
                            temp_board.push(move)
                        except:
                            break
                    self.analysis_text.insert(tk.END, "\n\n")
                    
                depth = info.get("depth", 0)
                nodes = info.get("nodes", 0)
                nps = info.get("nps", 0)
                
                stats = f"深度: {depth}"
                if nodes > 0:
                    if nodes > 1000000:
                        stats += f" | 节点数: {nodes/1000000:.1f}M"
                    elif nodes > 1000:
                        stats += f" | 节点数: {nodes/1000:.1f}K"
                    else:
                        stats += f" | 节点数: {nodes}"
                if nps > 0:
                    if nps > 1000000:
                        stats += f" | 速度: {nps/1000000:.1f}M nps"
                    elif nps > 1000:
                        stats += f" | 速度: {nps/1000:.1f}K nps"
                        
                self.analysis_text.insert(tk.END, stats, 'info')
                
            except Exception as e:
                self.analysis_text.delete(1.0, tk.END)
                self.analysis_text.insert(tk.END, f"分析错误: {str(e)}\n", 'error')
                
        threading.Thread(target=analyze, daemon=True).start()
        
    def get_best_move(self):
        if not self.engine:
            messagebox.showwarning("警告", "请先加载引擎")
            return
            
        def find_best():
            try:
                self.analysis_text.delete(1.0, tk.END)
                self.analysis_text.insert(tk.END, "正在计算最佳着法...\n", 'info')
                
                result = self.engine.play(self.board, chess.engine.Limit(time=3.0))
                best_move = result.move
                
                if best_move:
                    san = self.board.san(best_move)
                    
                    self.selected_square = best_move.from_square
                    self.legal_moves = [best_move.to_square]
                    self.draw_board()
                    
                    self.analysis_text.delete(1.0, tk.END)
                    self.analysis_text.insert(tk.END, f"最佳着法: {san}\n\n", 'success')
                    self.analysis_text.insert(tk.END, "最佳着法已在棋盘上高亮显示\n", 'info')
                    self.analysis_text.insert(tk.END, "点击高亮的目标格子即可执行此着法", 'info')
                else:
                    self.analysis_text.delete(1.0, tk.END)
                    self.analysis_text.insert(tk.END, "无法找到最佳着法\n", 'error')
                    
            except Exception as e:
                self.analysis_text.delete(1.0, tk.END)
                self.analysis_text.insert(tk.END, f"错误: {str(e)}\n", 'error')
                
        threading.Thread(target=find_best, daemon=True).start()
        
    def toggle_auto_analysis(self):
        if self.auto_analyze_var.get():
            if not self.engine:
                self.auto_analyze_var.set(False)
                messagebox.showwarning("警告", "请先加载引擎")
                return
            self.is_analyzing = True
            self.start_auto_analysis()
        else:
            self.is_analyzing = False
            
    def start_auto_analysis(self):
        if not self.is_analyzing or not self.engine:
            return
            
        def auto_analyze():
            try:
                with self.engine.analysis(self.board) as analysis:
                    for info in analysis:
                        if not self.is_analyzing:
                            break
                            
                        self.master.after(0, lambda i=info: self.update_auto_analysis(i))
                        
                        if info.get("depth", 0) >= 20:
                            break
                            
            except Exception as e:
                print(f"自动分析错误: {e}")
                
        self.analysis_thread = threading.Thread(target=auto_analyze, daemon=True)
        self.analysis_thread.start()
        
    def update_auto_analysis(self, info):
        if not self.is_analyzing:
            return
            
        self.analysis_text.delete(1.0, tk.END)
        
        score = info.get("score", None)
        if score:
            pov_score = score.relative
            if pov_score.is_mate():
                mate_in = pov_score.mate()
                if mate_in > 0:
                    eval_text = f"♔ 白方 {mate_in} 步将死"
                else:
                    eval_text = f"♚ 黑方 {-mate_in} 步将死"
            else:
                cp = pov_score.score()
                if cp is not None:
                    cp = cp / 100.0
                    eval_text = f"评估: {cp:+.2f}"
                else:
                    eval_text = "评估: 0.00"
        else:
            eval_text = "分析中..."
            
        self.analysis_text.insert(tk.END, eval_text + "\n", 'info')
        
        pv = info.get("pv", [])
        if pv:
            temp_board = self.board.copy()
            pv_text = ""
            for i, move in enumerate(pv[:8]):
                try:
                    san = temp_board.san(move)
                    if i % 2 == 0:
                        move_num = temp_board.fullmove_number
                        pv_text += f"{move_num}. "
                    pv_text += f"{san} "
                    temp_board.push(move)
                except:
                    break
            self.analysis_text.insert(tk.END, f"变化: {pv_text}\n")
            
        depth = info.get("depth", 0)
        self.analysis_text.insert(tk.END, f"深度: {depth} ", 'info')
        self.analysis_text.insert(tk.END, "[自动分析中...]", 'warning')
        
    def toggle_coordinates(self):
        self.show_coordinates = self.show_coords_var.get()
        self.draw_board()
        
    def toggle_legal_moves(self):
        self.show_legal_moves = self.show_moves_var.get()
        self.draw_board()
        
    def on_closing(self):
        self.is_analyzing = False
        if self.engine:
            self.engine.quit()
        self.master.destroy()


